#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
数据统计面板
"""

import sys
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, 
                             QLabel, QComboBox, QPushButton, QDateEdit, QTableWidget, QTableWidgetItem, QHeaderView, QSizePolicy)
from PyQt5.QtCore import QDate, Qt, QEvent, QRectF, QPointF, QSizeF, QObject, pyqtSignal, QEasingCurve, QPropertyAnimation
from PyQt5.QtCore import QMargins
from PyQt5.QtCore import QDate, Qt
from PyQt5.QtGui import QPainter, QFont, QBrush, QLinearGradient, QColor

from PyQt5.QtChart import QChart, QChartView, QBarSeries, QBarSet, QBarCategoryAxis, QValueAxis, QPieSeries, QPieSlice, QLegend
from PyQt5.QtCore import Qt as QtCore
from database import Database


class IOSBarChart(QChartView):
    """iOS风格条形图"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setRenderHint(QPainter.Antialiasing)
        self.setBackgroundBrush(Qt.transparent)
        
        # 创建图表
        self.chart = QChart()
        self.chart.setBackgroundRoundness(12)
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setAnimationDuration(800)
        self.chart.setAnimationEasingCurve(QEasingCurve.OutBack)
        
        # 创建系列
        self.series = QBarSeries()
        self.series.setBarWidth(0.6)
        self.series.hovered.connect(self.onBarHovered)
        
        self.chart.addSeries(self.series)
        
        # 视觉效果
        self.setChart(self.chart)
        
    def generateGradientColor(self, index):
        """生成iOS风格的渐变色"""
        colors = [
            QColor("#4A6CF7"),
            QColor("#9B59B6"),
            QColor("#31C48D"),
            QColor("#4A6CF7"),
            QColor("#F4C22B"),
            QColor("#FF9500")
        ]
        
        return colors[index % len(colors)]
        
    def applyGlassEffect(self):
        """应用透明效果"""
        pass
        
    def onBarHovered(self, status, index, bar_set):
        """悬停交互效果"""
        if status:
            # 悬停放大效果
            animation = QPropertyAnimation(bar_set, b"barWidth")
            animation.setDuration(200)
            animation.setStartValue(0.6)
            animation.setEndValue(0.7)
            animation.setEasingCurve(QEasingCurve.OutBack)
            animation.start()
            
            # 显示详细信息
            self.showTooltip(index, bar_set)
        else:
            # 恢复原大小
            animation = QPropertyAnimation(bar_set, b"barWidth")
            animation.setDuration(300)
            animation.setStartValue(0.7)
            animation.setEndValue(0.6)
            animation.start()
            
    def showTooltip(self, index, bar_set):
        """显示悬浮提示"""
        # 实现略 - 创建半透明卡片显示详细信息

class ReportWidget(QWidget):
    """数据统计面板"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setup_ui()
        self.load_data()
        
    def setup_ui(self):
        """设置界面"""
        layout = QVBoxLayout()
        
        # 顶部控制栏
        control_layout = QHBoxLayout()
        
        # 年份选择
        self.year_combo = QComboBox()
        self.year_combo.addItems([str(year) for year in range(2020, 2030)])
        self.year_combo.setCurrentText(str(QDate.currentDate().year()))
        self.year_combo.currentTextChanged.connect(self.load_data)
        control_layout.addWidget(QLabel("年份:"))
        control_layout.addWidget(self.year_combo)
        
        # 月份选择
        self.month_combo = QComboBox()
        self.month_combo.addItems([f"{month:02d}" for month in range(1, 13)])
        self.month_combo.setCurrentText(f"{QDate.currentDate().month():02d}")
        self.month_combo.currentTextChanged.connect(self.load_data)
        control_layout.addWidget(QLabel("月份:"))
        control_layout.addWidget(self.month_combo)
        
        # 刷新按钮
        refresh_button = QPushButton("刷新")
        refresh_button.clicked.connect(self.load_data)
        control_layout.addWidget(refresh_button)
        
        control_layout.addStretch()
        layout.addLayout(control_layout)
        
        # 图表区域
        chart_layout = QGridLayout()
        
        # 月度收支趋势图
        self.income_expense_chart_view = QChartView()
        self.income_expense_chart_view.setRenderHint(QPainter.Antialiasing)
        chart_layout.addWidget(QLabel("月度收支趋势"), 0, 0)
        chart_layout.addWidget(self.income_expense_chart_view, 1, 0)
        
        # 分类占比环形图
        self.category_chart_view = QChartView()
        self.category_chart_view.setRenderHint(QPainter.Antialiasing)
        chart_layout.addWidget(QLabel("分类占比"), 0, 1)
        chart_layout.addWidget(self.category_chart_view, 1, 1)
        
        # 添加收支趋势表格
        self.trend_table = QTableWidget()
        self.trend_table.setColumnCount(4)  # 增加对方名称列
        self.trend_table.setHorizontalHeaderLabels(["日期", "收入", "支出", "对方名称"])
        self.trend_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 启用排序功能
        self.trend_table.setSortingEnabled(True)
        self.trend_table.setMouseTracking(True)  # 启用鼠标跟踪
        self.trend_table.cellEntered.connect(self.handle_table_cell_hover)
        # 安装事件过滤器来处理鼠标离开表格
        self.trend_table.setMouseTracking(True)
        self.trend_table.installEventFilter(self)
        chart_layout.addWidget(QLabel("收支趋势详情"), 2, 0)
        chart_layout.addWidget(self.trend_table, 3, 0, 1, 2)  # 跨两列
        
        layout.addLayout(chart_layout)
        
        # 摘要信息
        self.summary_label = QLabel()
        layout.addWidget(self.summary_label)
        
        self.setLayout(layout)
        
    def load_data(self):
        """加载数据并更新图表"""
        year = int(self.year_combo.currentText())
        month = int(self.month_combo.currentText())
        
        # 获取月度汇总数据
        db = Database()
        monthly_data = self.get_monthly_summary(db, year, month)
        
        # 获取分类汇总数据
        category_data = self.get_category_summary(db, year, month)
        
        # 更新图表
        self.update_income_expense_chart(monthly_data)
        self.update_category_chart(category_data)  # 传递必要参数
        
        # 更新摘要信息
        self.update_summary(monthly_data)
        
    def update_income_expense_chart(self, data):
        """更新收支趋势图"""
        # 创建iOS风格条形图
        ios_chart = IOSBarChart()
        
        # 添加数据
        categories = []
        income_values = []
        expense_values = []
        
        for item in data:
            # 只显示日期部分（日）
            date_parts = item['date'].split('-')
            if len(date_parts) >= 3:
                day = date_parts[2]
                categories.append(day)
            else:
                categories.append(item['date'])
            income_values.append(item['income'])
            expense_values.append(item['expense'])
        
        # 创建收入和支出数据集
        income_set = QBarSet("收入")
        expense_set = QBarSet("支出")
        
        for i, (income, expense) in enumerate(zip(income_values, expense_values)):
            income_set.append(income)
            expense_set.append(expense)
            income_set.setColor(ios_chart.generateGradientColor(i * 2))
            expense_set.setColor(ios_chart.generateGradientColor(i * 2 + 1))
        
        # 添加数据集到系列
        ios_chart.series.append(income_set)
        ios_chart.series.append(expense_set)
        
        # 创建坐标轴
        axis_x = QBarCategoryAxis()
        axis_x.append(categories)
        axis_x.setLabelsColor(QColor("#8E8E93"))
        axis_x.setGridLineVisible(False)
        
        max_value = max(max(income_values), max(expense_values)) if income_values and expense_values else 0
        axis_y = QValueAxis()
        axis_y.setRange(0, max_value * 1.2)
        axis_y.setLabelFormat("¥%d")
        axis_y.setLabelsColor(QColor("#8E8E93"))
        axis_y.setGridLineColor(QColor(142, 142, 147, 50))
        
        ios_chart.chart.addAxis(axis_x, Qt.AlignBottom)
        ios_chart.series.attachAxis(axis_x)
        ios_chart.chart.addAxis(axis_y, Qt.AlignLeft)
        ios_chart.series.attachAxis(axis_y)
        
        # 设置标题
        ios_chart.chart.setTitle("月度收支趋势")
        
        # 设置图表视图
        self.income_expense_chart_view.setChart(ios_chart.chart)
        
        # 同时更新表格数据
        self.update_trend_table(data)
        
    def update_category_chart(self, category_data):  # 添加必要参数
        """更新分类占比图"""
        # 创建iOS风格饼状图
        ios_pie_chart = IOSPieChart()
        
        # 如果没有数据，显示提示信息
        if not category_data:
            ios_pie_chart.series.append("暂无数据", 1)
            slice = ios_pie_chart.series.slices()[0]
            slice.setLabelVisible(True)
        else:
            # 添加数据
            for i, item in enumerate(category_data):
                slice = ios_pie_chart.series.append(f"{item['category']} ({item['amount']:.2f})", item['amount'])
                # 设置颜色
                slice.setColor(ios_pie_chart.generateGradientColor(i))
                # 设置标签始终可见
                slice.setLabelVisible(True)
                slice.setLabelPosition(QPieSlice.LabelOutside)
                
        # 为饼图添加悬停和点击交互
        ios_pie_chart.series.hovered.connect(self.handle_slice_hovered)
        ios_pie_chart.series.clicked.connect(self.handle_slice_clicked)
        
        # 设置图例
        ios_pie_chart.chart.legend().setVisible(True)
        ios_pie_chart.chart.legend().setAlignment(Qt.AlignBottom)
        ios_pie_chart.chart.legend().setShowToolTips(True)
        
        # 设置标题
        ios_pie_chart.chart.setTitle("分类占比")
        
        # 设置图表视图
        self.category_chart_view.setChart(ios_pie_chart.chart)
        
        # 调整图表视图大小策略
        self.category_chart_view.setMinimumSize(500, 400)  # 增加最小尺寸
        self.category_chart_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)  # 设置大小策略
        
    def update_summary(self, data):
        """更新摘要信息"""
        total_income = sum(item['income'] for item in data)
        total_expense = sum(item['expense'] for item in data)
        balance = total_income - total_expense
        
        summary_text = f"<b>摘要:</b> 总收入: ¥{total_income:.2f} | 总支出: ¥{total_expense:.2f} | 结余: ¥{balance:.2f}"
        self.summary_label.setText(summary_text)
        
    def get_monthly_summary(self, db, year, month):
        """获取月度汇总数据"""
        import calendar
        days_in_month = calendar.monthrange(year, month)[1]
        
        # 构造查询日期范围
        start_date = f'{year}-{month:02d}-01 00:00:00'
        end_date = f'{year}-{month:02d}-{days_in_month:02d} 23:59:59'
        
        # 查询数据库
        transactions = db.get_transactions(start_date, end_date)
        
        # 按日期汇总数据
        daily_data = {}
        for transaction in transactions:
            # transaction格式: (id, timestamp, amount, type, category, payee, source, note)
            timestamp = transaction[1]
            amount = transaction[2]
            type = transaction[3]
            payee = transaction[5]  # 对方名称
            
            # 提取完整的日期部分
            date_part = timestamp.split('T')[0] if 'T' in timestamp else timestamp.split(' ')[0]
            
            # 初始化每日数据
            if date_part not in daily_data:
                daily_data[date_part] = {'income': 0.0, 'expense': 0.0, 'payee_list': set()}
            
            # 累加金额
            if type == '收入':
                daily_data[date_part]['income'] += amount
            elif type == '支出':
                daily_data[date_part]['expense'] += abs(amount)
            
            # 添加对方名称
            if payee:
                daily_data[date_part]['payee_list'].add(payee)
        
        # 构造返回数据
        data = []
        for day in range(1, days_in_month + 1):
            date_str = f'{year}-{month:02d}-{day:02d}'
            if date_str in daily_data:
                payee_list = daily_data[date_str]['payee_list']
                payee_str = ', '.join(sorted(payee_list)) if payee_list else ''
                data.append({
                    'date': date_str,
                    'income': daily_data[date_str]['income'],
                    'expense': daily_data[date_str]['expense'],
                    'payee': payee_str
                })
            else:
                data.append({
                    'date': date_str,
                    'income': 0.0,
                    'expense': 0.0,
                    'payee': ''
                })
            
        return data
    
    def update_trend_table(self, data):
        """更新收支趋势表格"""
        # 设置表格行数
        self.trend_table.setRowCount(len(data))
        
        # 填充表格数据
        for row, item in enumerate(data):
            # 日期列
            date_item = QTableWidgetItem(item['date'])
            date_item.setFlags(date_item.flags() & ~Qt.ItemIsEditable)  # 设置为不可编辑
            self.trend_table.setItem(row, 0, date_item)
            
            # 收入列
            income_item = QTableWidgetItem(f"{item['income']:.2f}")
            income_item.setFlags(income_item.flags() & ~Qt.ItemIsEditable)
            income_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self.trend_table.setItem(row, 1, income_item)
            
            # 支出列
            expense_item = QTableWidgetItem(f"{item['expense']:.2f}")
            expense_item.setFlags(expense_item.flags() & ~Qt.ItemIsEditable)
            expense_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            self.trend_table.setItem(row, 2, expense_item)
            
            # 对方名称列
            payee_item = QTableWidgetItem(item['payee'])
            payee_item.setFlags(payee_item.flags() & ~Qt.ItemIsEditable)
            self.trend_table.setItem(row, 3, payee_item)
        
        # 调整列宽
        self.trend_table.resizeColumnsToContents()
    
    def handle_table_cell_hover(self, row, column):
        """处理表格单元格悬停事件"""
        # 恢复之前高亮的行
        self.restore_table_highlight()
        
        # 高亮显示当前行
        for col in range(self.trend_table.columnCount()):
            item = self.trend_table.item(row, col)
            if item:
                # 保存原始背景色
                if not hasattr(item, 'original_background'):
                    item.original_background = item.background()
                # 设置高亮背景色
                item.setBackground(Qt.yellow)
        
        # 在状态栏或提示信息中显示当前行的详细信息
        date_item = self.trend_table.item(row, 0)
        income_item = self.trend_table.item(row, 1)
        expense_item = self.trend_table.item(row, 2)
        payee_item = self.trend_table.item(row, 3)
        
        if date_item and income_item and expense_item:
            date = date_item.text()
            income = income_item.text()
            expense = expense_item.text()
            payee = payee_item.text() if payee_item else ''
            print(f"悬停在 {date} 日: 收入 {income}, 支出 {expense}, 对方 {payee}")
    
    def restore_table_highlight(self):
        """恢复表格高亮"""
        # 恢复所有单元格的原始背景色
        for row in range(self.trend_table.rowCount()):
            for col in range(self.trend_table.columnCount()):
                item = self.trend_table.item(row, col)
                if item and hasattr(item, 'original_background'):
                    item.setBackground(item.original_background)
    
    def eventFilter(self, obj, event):
        """事件过滤器，处理鼠标离开表格事件"""
        if obj == self.trend_table:
            if event.type() == event.Leave:
                # 鼠标离开表格时恢复高亮
                self.restore_table_highlight()
                return True
        return super().eventFilter(obj, event)
        
    def get_category_summary(self, db, year, month):
        """获取分类汇总数据"""
        import calendar
        days_in_month = calendar.monthrange(year, month)[1]
        
        # 构造查询日期范围
        start_date = f'{year}-{month:02d}-01 00:00:00'
        end_date = f'{year}-{month:02d}-{days_in_month:02d} 23:59:59'
        
        # 查询数据库，只获取支出类型的交易以提高性能
        transactions = db.get_transactions(start_date, end_date, '支出')
        
        # 按分类汇总支出数据
        category_data = {}
        for transaction in transactions:
            # transaction格式: (id, timestamp, amount, type, category, payee, source, note)
            amount = transaction[2]
            type = transaction[3]
            category = transaction[4]
            
            # 只统计支出
            if type == '支出':
                # 处理分类显示，如果是一级|二级格式，只使用二级分类
                if '|' in category:
                    category_parts = category.split('|')
                    if len(category_parts) >= 2 and category_parts[1]:
                        category = category_parts[1]
                    else:
                        category = category_parts[0]
                
                if category not in category_data:
                    category_data[category] = 0.0
                category_data[category] += abs(amount)
        
        # 构造返回数据
        return [{'category': category, 'amount': amount} 
                for category, amount in category_data.items()]
    
    def handle_slice_hovered(self, slice, state):
        """处理饼图扇形悬停事件"""
        if state:
            # 悬停时放大扇形
            slice.setExploded(True)
            slice.setLabelVisible(True)
        else:
            # 鼠标离开时恢复
            slice.setExploded(False)
            # 只有较大份额才保持标签可见
            if slice.value() > slice.series().sum() * 0.1:
                slice.setLabelVisible(True)
            else:
                slice.setLabelVisible(False)
    
    def handle_slice_clicked(self, slice):
        """处理饼图扇形点击事件"""
        # 显示点击的扇形信息
        label = slice.label()
        value = slice.value()
        percentage = (value / slice.series().sum()) * 100
        print(f"点击了: {label}, 金额: {value:.2f}, 占比: {percentage:.1f}%")
        # 这里可以添加更多交互逻辑，比如显示详细信息的对话框
        from PyQt5.QtWidgets import QMessageBox
        QMessageBox.information(self, "饼图详情", f"分类: {label}\n金额: {value:.2f}\n占比: {percentage:.1f}%")
        

class IOSPieChart(QChartView):
    """iOS风格饼状图"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setRenderHint(QPainter.Antialiasing)
        self.setBackgroundBrush(Qt.transparent)
        
        # 创建图表
        self.chart = QChart()
        self.chart.setBackgroundRoundness(12)
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setAnimationDuration(800)
        self.chart.setAnimationEasingCurve(QEasingCurve.OutBack)
        
        # 创建系列
        self.series = QPieSeries()
        self.series.setHoleSize(0.4)  # 设置为环形图
        self.series.hovered.connect(self.onSliceHovered)
        
        self.chart.addSeries(self.series)
        
        # 视觉效果
        self.setChart(self.chart)
        self.applyGlassEffect()
        
    def generateGradientColor(self, index):
        """生成iOS风格的渐变色"""
        colors = [
            QColor("#4A6CF7"),
            QColor("#9B59B6"),
            QColor("#31C48D"),
            QColor("#F4C22B"),
            QColor("#FF9500"),
            QColor("#FF6B6B"),
            QColor("#6C5CE7"),
            QColor("#A29BFE"),
            QColor("#FD79A8"),
            QColor("#FDCB6E")
        ]
        
        return colors[index % len(colors)]
        
    def applyGlassEffect(self):
        """应用透明效果"""
        pass
        
    def onSliceHovered(self, slice, state):
        """悬停交互效果"""
        if state:
            # 悬停放大效果
            animation = QPropertyAnimation(slice, b"explodeDistanceFactor")
            animation.setDuration(200)
            animation.setStartValue(0)
            animation.setEndValue(0.15)
            animation.setEasingCurve(QEasingCurve.OutBack)
            animation.start()
            
            # 显示标签
            slice.setLabelVisible(True)
        else:
            # 恢复原大小
            animation = QPropertyAnimation(slice, b"explodeDistanceFactor")
            animation.setDuration(300)
            animation.setStartValue(0.15)
            animation.setEndValue(0)
            animation.start()
            
            # 隐藏标签（如果占比小）
            if slice.percentage() < 0.05:  # 小于5%的扇形隐藏标签
                slice.setLabelVisible(False)